﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using Newtonsoft.Json;
using T.ServiceComponent.Database.Service;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Metadata.Entity.DataModel;
using T.ServiceComponent.Error;
using T.FAS.Runtime.Base.Entity;

namespace T.FAS.Runtime.DataModel.Dao
{
    public class DatabaseLogic
    {
        private readonly DatabaseELBDao _databaseDao = new DatabaseELBDao();
        private readonly DatabaseConfigELBDao _databaseConfigDao = new DatabaseConfigELBDao();
        private readonly DatabaseValidator _databaseValidator = new DatabaseValidator();

        public const string MetaDataID = "Database";
        public const string MetaDataName = "数据库";

        public List<Database> GetDatabases(Dictionary<string, string> filter)
        {
            return _databaseDao.GetDatabases(filter);
        }

        public Database GetDatabaseByID(string databaseID)
        {
            return _databaseDao.GetDatabaseByID(databaseID);
        }

        /// <summary>
        /// 保存数据库，级联保存数据库配置
        /// </summary>
        /// <param name="database"></param>
        public void AddDatabase(Database database)
        {
            _databaseValidator.CreateMetadata(database);

            ArrayList databaseConfigs = new ArrayList();

            //DB不再是元数据，GUID由自己生成
            if(string.IsNullOrEmpty(database.ID))
                database.ID = Guid.NewGuid().ToString();

            if (database.DatabaseConfigs != null && database.DatabaseConfigs.Count > 0)
            {
                database.DatabaseConfigs.ForEach(config =>
                {
                    config.ID = Guid.NewGuid().ToString();
                    config.DatabaseID = database.ID;
                    config.Creator = database.Creator;
                    config.CreateTime = database.CreateTime;
                    config.LastModifier = database.LastModifier;
                    config.LastModifyTime = database.LastModifyTime;
                });
                databaseConfigs.AddRange(database.DatabaseConfigs);
            }
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted}))
                {
                    //做新增Unique Check
                    if (CheckUnique(database))
                    {
                        throw new FasException(DataModelErrorCode.DB.UniqueCheckError, $"不满足唯一性验证，Code:{database.Code}; DbType:{database.DbType}");
                    }

                    _databaseDao.AddDatabase(database);
                    if (database.DatabaseConfigs != null && database.DatabaseConfigs.Count > 0)
                    {
                        _databaseConfigDao.AddDatabaseConfigList(databaseConfigs); 
                    }
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DB.CreateError, "数据库元数据保存失败", e);
            } 
        }

        public void AddDatabaseList(List<Database> databaseList)
        {
            _databaseDao.AddDatabaseList(databaseList);
        }

        public void UpdateDatabase(Database database)
        {
            _databaseValidator.UpdateMetadata(database);
            DeleteDatabase(new Dictionary<string, string>()
            {
                { "ID", database.ID },
            });
            AddDatabase(database);
            //databaseDao.UpdateDatabase(database);
        }

        /// <summary>
        /// 删除数据库，级联删除数据库配置
        /// </summary>
        /// <param name="filter"></param>
        public void DeleteDatabase(Dictionary<string, string> filter)
        {
            try
            {
                _databaseValidator.DeleteMetadata(filter["ID"]);
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted}))
                {
                    _databaseDao.DeleteDatabase(filter);
                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.DB.DeleteError, "数据库元数据删除失败", e);
            }
        }

        public void DeleteDatabaseList(List<string> idList)
        {
            _databaseDao.DeleteDatabaseList(idList);
        }

        public int CheckUnique(Dictionary<string, string> filter)
        {
            return _databaseDao.CheckUnique(filter);
        }

        public List<DatabaseConfig> GetDatabaseConfigs(Dictionary<string, string> filter)
        {
            return _databaseConfigDao.GetDatabaseConfigs(filter);
        }

        public DatabaseConfig GetDatabaseConfigByID(string databaseConfigID)
        {
            return _databaseConfigDao.GetDatabaseConfigByID(databaseConfigID);
        }

        public void AddDatabaseConfig(DatabaseConfig databaseConfig)
        {
            _databaseConfigDao.AddDatabaseConfig(databaseConfig);
        }

        public void AddDatabaseConfigList(ArrayList databaseConfigs)
        {
            _databaseConfigDao.AddDatabaseConfigList(databaseConfigs);
        }

        public void UpdateDatabaseConfig(DatabaseConfig DatabaseConfig)
        {
            _databaseConfigDao.UpdateDatabaseConfig(DatabaseConfig);
        }

        public void DeleteDatabaseConfig(Dictionary<string, string> filter)
        {
            _databaseConfigDao.DeleteDatabaseConfig(filter); 
        }


        /// <summary>
        /// DB保存或修改唯一性验证
        /// </summary>
        /// <param name="database">DB实体</param>
        /// <param name="OpeType">0:新增; 1:修改</param>
        /// <returns>true:表示数据库中存在重复数据，无法保存; false:表示入参DB在数据库中唯一，可以进行保存</returns>
        public bool CheckUnique(Database metaDataContent, int OpeType = 0)
        {
            var database = metaDataContent;
            var filter = new Dictionary<string, string>
            {
                { "Code", database.Code },
                { "DbType", database.DbType },
                { "TenantID", database.TenantID }
            };
            if (OpeType == 1)
            {
                filter["ID"] = database.ID;
            }
            var cnt = _databaseDao.CheckUnique(filter);
            return cnt > 0;
        }
    }
}
